﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Xml.Serialization;
using NUnit.Framework;

namespace Universe.SimpleQueue.Tests
{
    /*[TestFixture]*/
    [Explicit]
    public class TestDefenitions
    {

        private string QueueName;
        private static int Counter = 0;

        protected virtual Func<SimpleQueue.IConnectionInfo> ConnectionFactory
        {
            get
            {
                return Env.SQLCE_With_Explicit_ReadCommitted_Isolatated_Transactions;
            }
        }

        [TestFixtureSetUp]
        public void Setup()
        {
            SimpleQueue queue = new SimpleQueue(ConnectionFactory);
            queue.PurgeOldMessages(3600L*24*365*200);
            QueueName = "Queue! " + Guid.NewGuid();
            SimpleQueue.LocalStat.Clean();
        }


        [Test]
        public void Empty_Queue_Is_Empty()
        {
            Universe.SimpleQueue.SimpleQueue sq = new Universe.SimpleQueue.SimpleQueue(ConnectionFactory);
            var message = sq.NextDelivery("no such queue: " + Guid.NewGuid());
            Assert.IsNull(message);
        }

        [Test]
        public void Thousand_Reads_From_Empty_Queue()
        {
            Universe.SimpleQueue.SimpleQueue sq = new Universe.SimpleQueue.SimpleQueue(ConnectionFactory);
            for (int i = 0; i < 100; i++)
            {
                var message = sq.NextDelivery("no such queue: " + Guid.NewGuid());
                Assert.IsNull(message);
            }
        }

        [Test]
        public void Queue_With_The_One_Message()
        {
            string queueName = "Single Message Only Copy: " + Guid.NewGuid();
            string uniqueKey = "The One Copy: " + Guid.NewGuid();

            Universe.SimpleQueue.SimpleQueue sq = new Universe.SimpleQueue.SimpleQueue(ConnectionFactory);
            bool isNew = sq.Publish(queueName, uniqueKey, new byte[] { 1, 2, 3 });
            Assert.IsTrue(isNew, "Unique message always publishes");

            sq = new SimpleQueue(ConnectionFactory);
            var message = sq.NextDelivery(queueName);
            Assert.IsNotNull(message);
            Assert.AreEqual(uniqueKey, message.OptionalKey);
            Assert.AreEqual(new byte[] { 1, 2, 3 }, message.Payload);
        }

        [Test]
        public void Queue_With_The_One_Message_Copy()
        {
            string queueName = "Single Message Only Copy: " + Guid.NewGuid();
            string uniqueKey = "The One Copy: " + Guid.NewGuid();

            SimpleQueue sq = new SimpleQueue(ConnectionFactory);
            bool isNew = sq.Publish(queueName, uniqueKey, new byte[] { 1, 2, 3 });
            Assert.IsTrue(isNew, "Unique message always publishes");

            var status = sq.GetMessageStatus(uniqueKey);
            Assert.IsNotNull(status, "Status of message is present, so the Message is stored in the DB");

            sq = new SimpleQueue(ConnectionFactory);
            var message = sq.NextDelivery(queueName);
            Assert.IsNotNull(message);
            Assert.AreEqual(uniqueKey, message.OptionalKey);
            Assert.AreEqual(new byte[] { 1, 2, 3 }, message.Payload);
        }

        [Test]
        public void Publish_100()
        {
            var sq = new SimpleQueue(ConnectionFactory);
            for(int i=0; i<100; i++)
            {
                sq.Publish(QueueName, new byte[] { 1, 2, 3 });
            }
        }


        private static int NextCounter
        {
            get { return Interlocked.Increment(ref Counter); }
        }

        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            Trace.WriteLine(SimpleQueue.LocalStat.AsConsoleTable());
        }
    }
}
